-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[GR-54697] Implement debuginfo generation at image-runtime. #10522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
6dfef33
to
a6101eb
Compare
Even if we don't get the GDB changes upstream in time this PR should be merged soon. The Debuginfo generation speedup due to parallelization plus the fix to make our DWARF5 work with GDB 16 or later justifies having this on master. |
704775a
to
b05b63f
Compare
8866afc
to
3e9f02a
Compare
040181d
to
ac8e19c
Compare
f6cb0b8
to
da7b49d
Compare
@adinn this PR will likely be merged mid or end of next week. If you have any questions or comments, this would be a good time. cc @dominikmascherbauer |
4006038
to
b3e78d8
Compare
This is not required anymore as we now use GDB opaque types to refer to already at-build-time-defined types from the run-time debuginfo generator. |
dddcdb2
to
3234927
Compare
20dd01d
to
c2ad2f0
Compare
…g information generation Implement the GDB JIT compilation interface Split off a shared debug information generator for use at image build-time and run-time Rework debug entries Parallelize debug information generation Add LocalVariableTable to SubstrateMethod Add tests for run-time debug information generation Refactor and rework gdb-debughelpers Make BFDNameProvider usable at image run-time Update Line section to DWARF5, fix bug when loading debug info in recent GDB versions (>= GDB 16) Add support for lazy deoptimization for frame unwinder and frame filter Implement opaque type resolution for runtime debug information in GDB Updates to CV debug information to be compatible with reworked debug information generation
c2ad2f0
to
0a847fd
Compare
Advanced Debugging of Native Images in GDB
Goals
Debug info produced during a Native Image build will be referred to as AOT Debug Info, and debug info produced at image run-time as Run-time Debug Info.
Overview
On Linux, Native Image supports generating images with DWARF debug info.
This allows to use a native debugger (e.g. GDB) to debug native images.
This PR builds on the already available debug info generator and DWARF debug info.
With the existing implementaiton, debug info generation is part of the Native Image builder and only runs as part of the Native Image build process to produce AOT Debug Info.
For run-time compilations, there is no debug info generator available to produce run-time debug info.
To fix this, this PR reworks the debug info generator to be also usable at image run-time.
With a run-time debug info generator, we can then generate debug info whenever a new method is compiled and registered into the run-time code-cache.
This Run-time debug info also needs to be disposed once the run-time compilation in the run-time code-cache is no longer valid (e.g. after deoptimization).
Updates to Debug Info Generation
In general, debug info generation works in two steps:
For this PR mainly focuses on 1 and writing ELF/DWARF debug info from 2 but not PECOFF/CV for Windows.
Debug Info Generator
Runs after all compilations are completed and makes use of:
With this information, the debug info generator produces debug entries.
This PR changes this step as follows:
Parallelize producing debug entries
-H:DebugInfoGenerationThreadCount=<threadCount>
by default same as image builderExtract a
SharedDebugInfoProvider
for use at image build-time and image run-time.Independent of the Native Image Builder.
Build-time implementation -> needs to generate as much debug info as possible. This is all classes, other types, methods, fields, compilations, locations of static fields and class constant objects.
Run-time implementation -> only needs to process the run-time compilation. For types, it just requires the name of a type and its type signature. This reduces the time and memory needed for generating and storing run-time debug info object files.
Run-time Debug Info Generation
Can be enabled via
-H:+RuntimeDebugInfo
.This adds the debug info generator into a Native Image (Only if run-time compilation support is enabled).
It only makes sense to use if the Native Image was built with debug info (
-g
).Therefore, a Native Image build with run-time debug info support usually at least take the following arguments:
Run-time debug info generation then works as follows:
What happens at image build-time:
What happens at image run-time:
Deoptimization
If a run-time compilation is invalidated the run-time code cache (for example, due to deoptimization), we also have to clean up the in-memory object file containing the run-time debug info in reverse order:
Tracking Run-time Debug Info
For each run-time compilation, we create a
Handle
that saves the current state of the run-time debug info (initialized, active, released) and a reference to the in-memory object file.If a code-cache change is observed, the handle gets updated.
Possible state for a handle are:
Interfacing with GDB
Once run-time debug info is generated, the debugger needs to be notified.
GDB introduces the GDB JIT Compilation Interface that allows us to notify GDB about run-time debug info.
To make use of the JIT compilation interface, we just need to create a
jit_code_entry
add it to the__jit_debug_descriptor
set the correctaction_flag
and call__jit_debug_register_code
.Implementation Details
The implementation for Native Image is written in SystemJava in
GdbJitInterface
.It contains two functions, one for adding a run-time debug info object file through a
jit_code_entry
:and one for removing it again:
Those methods are called after the code observer is notified on a run-time code cache change:
jit_code_entry
jit_code_entry
and callregisterJITCode
unregisterJITCode
and freejit_code_entry
Re-using AOT Debug Info
The initial idea for re-using AOT debug info was to make use of DWARF Type Units introduced in GR-56599.
DWARF Type Units mainly simplifies type references within DWARF debug information.
DWARF Type Units (TU)s
In contrast to regular type references that are relative to the start of a CU or the .debug_info section, TUs are referenced by a so-called type signature.
A type unit contains all static information about a type, for example:
It should not contain any relocatable information, this should be placed in a CU.
Each TU that represents a Java class has a corresponding CU (both in the .debug_info section).
The corresponding CU then holds debug information for static field locations and method compilation (including all debug information for inlined methods).
The type signature of a TU is stored in the TU header as follows (excerpt from objdump for
java.lang.Object
):The corresponding CU refers to the TU by the signature and adds debug information to this type:
Type references in Native Image debug info therefore looks as follows and can be used from anywhere within the same object file:
The plan was to make use of TUs to re-use type information from the AOT Debug Info in the Run-time Debug Info.
This requires a change in GDB to allow TU lookup across multiple object files.
As part of my work I implemented a patch to make this work within GDB dominikmascherbauer/binutils-gdb#1
However, this patch violates invariants about type ownership in GDB and will not be added as is to GDB.
Opaque Types
Instead, we still use TUs, but in combination with opaque types.
Opaque types are a concept of GDB (not defined in DWARF) and allow to reference type information by name across multiple object files.
An opaque type can only be a pointer to a DWARF struct, class, or union DIE, for example:
Using opaque types allows us to re-use type information from the AOT debug info in run-time debug info.
This makes up most of the debug information needed for run-time compilations.
In the run-time debug info, we just need to add the debug information for the compilation and use opaque types instead of writing the whole type hierarchy into the run-time debug info again.
Enhanced Debugging in GDB
We provide a Python script
gdb-debughelpers.py
that makes use of the GDB Python API.This improves the debugging experience of Native Images in the GDB command line.
Provides support for:
ArrayList
andHashMap
Usage Example
Compile Java file with all debug information, then build a Native Image with debug info.
Run-time debug info is tested against some manually triggered run-time compilations in
RuntimeCompileDebugInfoTest
.First build a jsvm image with run-time debug info support.
Then use it to run js code, for example: